package com.ccp.dev.workflow.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.model.BaseModel;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.form.service.FormDefService;
import com.ccp.dev.system.model.SysUser;
import com.ccp.dev.system.service.SysUserService;
import com.ccp.dev.workflow.bpmconst.BpmConst;
import com.ccp.dev.workflow.dao.AgentConditionDao;
import com.ccp.dev.workflow.dao.AgentDefModelDao;
import com.ccp.dev.workflow.dao.AgentSettingDao;
import com.ccp.dev.workflow.model.ActDefModel;
import com.ccp.dev.workflow.model.AgentCondition;
import com.ccp.dev.workflow.model.AgentDefModel;
import com.ccp.dev.workflow.model.AgentSetting;
import org.flowable.engine.TaskService;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ClassDescribe 代理设定 Service类
 * @author: fanruiqi
 * Date: 2019-09-20
 * Since:1
 * To change this template use File | Settings | File Templates.
 */
@Service
public class AgentSettingService extends BaseService<AgentSetting> {
    @Resource
    private AgentSettingDao agentSettingDao;
    @Resource
    private AgentConditionDao agentConditionDao;
    @Resource
    private AgentDefModelDao agentDefModelDao;
    @Resource
    private ActDefModelService actDefModelService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private FormDefService formDefService;
    @Resource
    private TaskService taskService;

    @Resource
    private AgentConditionService agentConditionService;

    /**
     * 获取部分代理的代理的流程
     * @param id
     * @return
     */
    public List<AgentDefModel> queryBySettingId(String id) {
        return agentDefModelDao.queryListBySettingId(id);
    }

    /**
     * 添加代理设置
     * @param agentSetting
     * @throws Exception
     */
    public void addAll(AgentSetting agentSetting){
        add(agentSetting);
        addSubList(agentSetting);
    }

    /**
     * 更新代理设置
     * @param agentSetting
     * @throws Exception
     */
    public void updateAll(AgentSetting agentSetting){
        update(agentSetting);
        delByPk(agentSetting.getId());
        addSubList(agentSetting);
    }

    /**
     * 添加获取条件代理的条件或部分代理的代理的流程
     * @param agentSetting
     * @throws Exception
     */
    public void addSubList(AgentSetting agentSetting)  {
        List<AgentCondition> agentConditionList=agentSetting.getAgentConditionList();
        if(BeanUtils.isNotEmpty(agentConditionList)){
            for(AgentCondition agentCondition:agentConditionList){
                agentCondition.setSettingId(agentSetting.getId());
                agentCondition.setId(UUIDUtils.getUUIDFor32());
                agentConditionDao.add(agentCondition);
            }
        }
        List<AgentDefModel> agentDefList=agentSetting.getAgentDefList();
        if(BeanUtils.isNotEmpty(agentDefList)){
            for(AgentDefModel agentDefModel:agentDefList){
                agentDefModel.setSettingId(agentSetting.getId());
                agentDefModel.setId(UUIDUtils.getUUIDFor32());
                agentDefModelDao.add(agentDefModel);
            }
        }
    }
    /**
     * 根据代理设置，删除代理的条件和代理的流程设置信息
     * @param id
     */
    private void delByPk(String  id){
        agentConditionDao.delBySettingId(id);
        agentDefModelDao.delBySettingId(id);
    }
    /**
     * 获取条件代理的条件
     * @param id
     * @return
     */

    public List<AgentCondition> queryAgentConditionList(String id) {
        return agentConditionDao.queryListBySettingId(id);
    }
    /**
     * 获取部分代理的代理的流程
     * @param id
     * @return
     */
    public List<AgentDefModel> queryAgentDefModelById(String id) {
        return agentDefModelDao.queryListBySettingId(id);
    }

    /**
     * 判断流程定义是否已经设置了有效部分或条件代理设置
     * @param flowKey 流程定义Key
     * @param settingId 排除的代理设置
     * @return
     * 	true 已经设置了有效的部分代理设置
     *  false 未设置有效的部分代理设置
     */
    public boolean isConflictAgainstPartialOrConditionByFlow(String flowKey, Date startTime, Date endTime, String authId, String settingId) {
        Map<String,Object> params = new HashMap<String, Object>();
        params.put("flowKey", flowKey);
        params.put("authId", authId);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
//		params.put("authType",  AgentSetting.AUTHTYPE_PARTIAL);
        params.put("enabled", AgentSetting.ENABLED_YES);
        if(StringUtil.isNotEmpty(settingId)) {
            params.put("id", settingId);
        }
        List<AgentSetting> settings = agentSettingDao.queryByFlowKey(flowKey,params);
        boolean flag=false;
        if(BeanUtils.isNotEmpty(settings)){
            flag=true;
        }
        return flag;
    }

    /**
     * 判断是否已经设置了有效全权代理设置
     * @param settingId 排除的代理设置
     * @return
     * 	true 已经设置了有效的条件代理设置
     *  false 未设置有效的条件代理设置
     */
    public boolean isConflictAgainstGeneral(Date startTime, Date endTime, String authId, String settingId,boolean isGeneral) {
        Map<String,Object> params = new HashMap<String, Object>();
        params.put("authId", authId);
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("enabled", AgentSetting.ENABLED_YES);
        if(isGeneral) {
            params.put("authType", AgentSetting.AUTHTYPE_GENERAL);
        }
        params.put("id", settingId);
        List<AgentSetting> settings = agentSettingDao.queryAgentByFilter(params);
        boolean flag=false;
        if(BeanUtils.isNotEmpty(settings)){
            flag=true;
        }
        return flag;
    }

    /**
     * 获取 代理人
     * <pre>
     * 	1.根据任务获取流程定义ID.
     * 	2.根据流程定义ID，当前用户id，当前日期获取流程代理定义。
     * 	3.根据流程代理定义获取任务的执行人。
     * 		1.全局
     * 		2.部分
     * 		3.条件代理
     * </pre>
     * @param delegateTask 代理任务
     * @param sysUserId 用户id
     */
    public SysUser getAgent(DelegateTask delegateTask, String sysUserId) {
        String procDefId = delegateTask.getProcessDefinitionId();
        ActDefModel actDefModel = actDefModelService.getByProcDefId(procDefId);
        //2020-03-06 jyq注释，将formVars的查询换为通过taskService查询，否则任务交接时这行报懒加载的错误
        //Map<String, Object> formVars = delegateTask.getVariables();
        Map<String, Object> formVars = taskService.getVariables(delegateTask.getId());

        // 判断当前任务是否为子流程任务，若为子流程任务，则取主流程的代理配置
        if (formVars.containsKey(BpmConst.FLOW_PARENT_PROCDEFID)) {
            String mainProcDefId = (String) formVars.get(BpmConst.FLOW_MAIN_PROCDEFID);
            actDefModel = actDefModelService.getByProcDefId(mainProcDefId);
        }

        String flowKey = actDefModel.getModelKey();
        SysUser sysUser = null;
        Date currentDate = new Date();

        // 获取代理配置
        AgentSetting agentSetting = getValidAgentSetting(flowKey, sysUserId, currentDate, false);
        if (BeanUtils.isNotEmpty(agentSetting)) {
            // 全局
            if (AgentSetting.AUTHTYPE_GENERAL == agentSetting.getAuthType().intValue()) {
                sysUser = sysUserService.getById(agentSetting.getAgentId());
            }
            // 部分代理
            else if(AgentSetting.AUTHTYPE_PARTIAL == agentSetting.getAuthType().intValue()) {
                sysUser = sysUserService.getById(agentSetting.getAgentId());
            }
            // 条件代理
            else if (AgentSetting.AUTHTYPE_CONDITION == agentSetting.getAuthType().intValue()) {
                String tableId = formDefService.getTableIdByModelId(actDefModel.getId());
                if (StringUtil.isNotEmpty(tableId)) {
                    List<AgentCondition> conditions = getAgentConditionList(agentSetting.getId());
                    for (AgentCondition condition : conditions) {
                        if (agentConditionService.conditionCheck(condition, tableId, formVars)) {
                            sysUser = sysUserService.getById(condition.getAgentId());
                            break;
                        }
                    }
                }
            }
        }
        return sysUser;
    }

    /**
     * 根据流程key、授权人和日期，取得代理设置
     * @param flowKey 流程key
     * @param sysUserId 授权人
     * @param currentDate 日期
     * @param cascade 级联查询标志。如果为true，将级联查询代理的流程和条件
     * @return
     */
    public AgentSetting getValidAgentSetting(String flowKey, String sysUserId, Date currentDate, boolean cascade) {
        AgentSetting setting = agentSettingDao.getValidByFlowAndAuthIdAndDate(flowKey, sysUserId, currentDate);

        if (setting != null) {
            if (cascade) {
                if (AgentSetting.AUTHTYPE_PARTIAL == setting.getAuthType().intValue()) {
                    List<AgentDefModel> agentDefModelList = queryAgentDefModelList(setting.getId());
                    setting.setAgentDefList(agentDefModelList);
                } else if (AgentSetting.AUTHTYPE_CONDITION == setting.getAuthType().intValue()) {
                    List<AgentCondition> agentConditionList = getAgentConditionList(setting.getId());
                    setting.setAgentConditionList(agentConditionList);
                }
            }
            return setting;
        }
        return null;
    }

    /**
     * 获取条件代理的条件
     * @param id 代理id
     * @return
     */
    public  List<AgentCondition> getAgentConditionList(String id) {
        return agentConditionDao.queryListBySettingId(id);
    }

    /**
     *  获取部分代理的代理的流程
     * @param id 根据id获取
     * @return
     */
    public List<AgentDefModel> queryAgentDefModelList(String id) {
        return agentDefModelDao.queryListBySettingId(id);
    }
}
